home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-11-19 | 10.3 KB | 498 lines | [TEXT/MPS ] |
- /*
- File: TestRandom.cp
-
- Contains: Tester for the TSimpleRandom class
-
- Copyright: © 1991-1994 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #ifndef __TESTRANDOM__
- #include "TestRandom.h"
- #endif
- #ifndef __STDLIB__
- #include <stdlib.h>
- #endif
- #ifndef __STRING__
- #include <String.h>
- #endif
-
- #define kTestArraySize 513
- #define kIterations 100
-
- /**********************************************************************
- ** PUBLIC Constructor/Destructor
- ***********************************************************************/
-
- Constructor(Random)
- Destructor(Random)
-
- //
- // Returns the square root, or the lower of the 2 numbers which straddle
- // the square root.
- //
- unsigned short FigSquareRoot(unsigned long num)
- {
- unsigned short ret = 46340; // square root of 0x7fffffff
- while (1)
- {
- long func = ret*ret - num;
- long derv = ret << 1;
- long dx = func/derv;
- ret -= (short)dx;
- if (dx == 0)
- {
- if (func > 0)
- ret -= 1;
- return ret;
- }
- }
- }
-
- #if USES68KINLINES
- extern "C"
- {
- #pragma parameter __D0 DoMod(__D0, __D1)
- unsigned short DoMod(unsigned long, unsigned short) =
- {
- 0x80c1, 0x4240, 0x4840
- // DIVU D1,D0; MOVE.W #0,D0; SWAP D0;
- };
- }
- #else
- inline unsigned short DoMod(unsigned long dividend, unsigned short divisor)
- {
- return dividend % divisor;
- }
- #endif
-
- //
- // Returns true if "num" is prime. WARNING: This routine CANNOT HANDLE EVEN NUMBERS!
- //
- Boolean IsPrime(unsigned long num)
- {
- unsigned short root = FigSquareRoot(num);
- unsigned short temp = (unsigned short)(num >> 16);
- unsigned short idx = temp;
- ldiv_t res;
- //
- // Set up idx to be the smallest odd number which will divide into "num"
- // without overflowing 65535
- //
- if (idx < 3)
- idx = 3;
- else
- if ((idx & 1) == 0)
- idx += 1;
- //
- // Try and disqualify the number using the fast divide stuff first!
- //
- while (idx <= root)
- {
- if (DoMod(num, idx) == 0) // If there is no remainder
- return false;
- idx += 2;
- }
- //
- // Then do it the hard way if it passed!
- //
- idx =1;
- if (root < temp)
- temp = root;
- while ((idx += 2) < temp)
- {
- res = ldiv(num, idx);
- if (res.rem == 0)
- return false;
- }
- return true;
- }
-
- double ExpectedRuns(double total, short inParm)
- {
- short foo = inParm + 1;
- double expect = total - total/double(foo);
- while (--foo > 1)
- {
- expect = expect/double(foo);
- }
- return expect;
- }
-
- /**********************************************************************
- ** PUBLIC InitTest
- ***********************************************************************/
-
- void TTestRandom::InitTest(BooleanParm, BooleanParm, int, char**)
- {
- TStandardPool* pool = GetPool();
-
- if (pool == NULL)
- {
- Printf("### ERROR: There is no global pool\n");
- return;
- }
-
- fTest = NULL;
-
- TRY
- fTest = new (pool) TFastRandom;
- CATCH_ALL
- ENDTRY
-
- if (fTest == NULL)
- {
- Printf("### ERROR: Could not create a TSimpleRandom object\n");
- return;
- }
- }
-
- /**********************************************************************
- ** PUBLIC RunTestIteration
- ***********************************************************************/
-
- void TTestRandom::RunTestIteration(BooleanParm, BooleanParm)
- {
- unsigned long idx;
- size_t jdx, kdx;
- size_t runs[kTestArraySize];
- size_t rawRuns[kTestArraySize];
- size_t counts[kTestArraySize];
- size_t rawCounts[kTestArraySize];
- unsigned long runPrev;
- unsigned long rawRunPrev;
- unsigned long rawPrev;
- unsigned long val;
- unsigned long rawVal;
-
- TStandardPool* pool = (TStandardPool*)TMemoryPool::RecoverPool(fTest);
-
- for (kdx = 0; kdx < 4; ++kdx)
- {
- char* className;
- unsigned long small = 0x7fffffff;
- unsigned long large = 0;
- unsigned long range;
- unsigned long clos = 0x7fffffff;
- size_t count = 0;
- size_t rawCount = 0;
-
- memset(runs, 0, sizeof(runs));
- memset(rawRuns, 0, sizeof(rawRuns));
- memset(counts, 0, sizeof(counts));
- memset(rawCounts, 0, sizeof(rawCounts));
-
- switch (kdx)
- {
- case 0:
- range = kMaxFastRandom;
- className = "TFastRandom";
- break;
-
- case 1:
- range = kMaxSimpleRandom;
- className = "TSimpleRandom";
- delete fTest;
- fTest = new TSimpleRandom;
- break;
-
- case 2:
- range = 0xffffffff;
- className = "TSimpleRandom";
- delete fTest;
- fTest = new TSimpleRandom(0, 314159261, 453448043);
- break;
-
- case 3:
- range = 0x7fff;
- className = "MPW Random";
- delete fTest;
- fTest = new TSimpleRandom(0x8000, 0x41c64e6d, 0x3039);
- break;
- }
-
- size_t divisor = size_t(range/kTestArraySize) + 1;
- unsigned long each = kIterations;
- unsigned long max = kTestArraySize*each;
- short runState = 0;
- short rawRunState = 0;
-
- Printf("\nINFO: Testing class %s\n", className);
-
- runPrev = fTest->GetRandomNumber(1, kTestArraySize);
- rawRunPrev = fTest->GetSeed();
- rawPrev = fTest->GetSeed();
-
- for (idx = 0; idx < max; ++idx)
- {
- unsigned short slot;
-
- val = fTest->GetRandomNumber(1, kTestArraySize);
- rawVal = fTest->GetSeed();
- if (val == 0 || val > kTestArraySize)
- {
- Printf("### ERROR: Value returned was %u\n", val);
- continue;
- }
- counts[val - 1] += 1;
- slot = (unsigned short)(rawVal/divisor);
- if (slot >= kTestArraySize)
- {
- Printf("### ERROR: Slot value was %u for %u/%u\n",
- slot, val, divisor);
- continue;
- }
- rawCounts[slot] += 1;
-
- //
- // Get the largest and smallest raw values seen
- //
- if (rawVal > large)
- large = rawVal;
- if (rawVal < small)
- small = rawVal;
- //
- // Get the smallest distance between 2 raw random numbers
- //
- unsigned long temp;
- if (rawVal != rawPrev)
- {
- if (rawVal > rawPrev)
- temp = rawVal - rawPrev;
- else
- temp = rawPrev - rawVal;
- if (temp < clos)
- clos = temp;
- }
- //
- // Save the previous number
- //
- rawPrev = rawVal;
- //
- // Update Run statistics
- //
- switch (runState)
- {
- // Just starting out, so see if we're an up or down run
- case 0:
- if (val >= runPrev)
- {
- runState = 1;
- count = 2;
- }
- else
- {
- runState = 2;
- count = 2;
- }
- break;
-
- // Handle Up Run
- case 1:
- if (val >= runPrev)
- {
- runPrev = val;
- count += 1;
- }
- else
- {
- if (count > kTestArraySize)
- runs[kTestArraySize - 1] += 1;
- else
- runs[count - 1] += 1;
- runState = 3;
- }
- break;
-
- // Handle Down Run
- case 2:
- if (val <= runPrev)
- {
- runPrev = val;
- count += 1;
- }
- else
- {
- if (count > kTestArraySize)
- runs[kTestArraySize - 1] += 1;
- else
- runs[count - 1] += 1;
- runState = 4;
- }
- break;
-
- // After Up Run
- case 3:
- runPrev = val;
- count = 1;
- runState = 2;
- break;
-
- // After Down Run
- case 4:
- runPrev = val;
- count = 1;
- runState = 1;
- break;
-
- }
- //
- // Update Run statistics
- //
- switch (rawRunState)
- {
- // Just starting out, so see if we're an up or down run
- case 0:
- if (rawVal >= rawRunPrev)
- {
- rawRunState = 1;
- rawCount = 2;
- }
- else
- {
- rawRunState = 2;
- rawCount = 2;
- }
- break;
-
- // Handle Up Run
- case 1:
- if (rawVal >= rawRunPrev)
- {
- rawRunPrev = rawVal;
- rawCount += 1;
- }
- else
- {
- if (rawCount > kTestArraySize)
- rawRuns[kTestArraySize - 1] += 1;
- else
- rawRuns[rawCount - 1] += 1;
- rawRunState = 3;
- }
- break;
-
- // Handle Down Run
- case 2:
- if (rawVal <= rawRunPrev)
- {
- rawRunPrev = rawVal;
- rawCount += 1;
- }
- else
- {
- if (rawCount > kTestArraySize)
- rawRuns[kTestArraySize - 1] += 1;
- else
- rawRuns[rawCount - 1] += 1;
- rawRunState = 4;
- }
- break;
-
- // After Up Run
- case 3:
- rawRunPrev = rawVal;
- rawCount = 1;
- rawRunState = 2;
- break;
-
- // After Down Run
- case 4:
- rawRunPrev = rawVal;
- rawCount = 1;
- rawRunState = 1;
- break;
-
- }
- }
- if (count > kTestArraySize)
- runs[kTestArraySize - 1] += 1;
- else
- runs[count - 1] += 1;
- if (rawCount > kTestArraySize)
- rawRuns[kTestArraySize - 1] += 1;
- else
- rawRuns[rawCount - 1] += 1;
- //
- // Output Chi-Squared statistic
- //
- {
- double a = 0.0;
- double b = double(each);
- for (jdx = 0; jdx < kTestArraySize; ++jdx)
- {
- double y = double(counts[jdx]) - b;
- a = a + (y*y);
- }
- a = a/b;
- unsigned long val = (unsigned long)(a*100);
- Printf("INFO: Chi-Squared value for Process Data was %u.%02u\n",
- val/100, val % 100);
-
- a = 0.0;
- for (jdx = 0; jdx < kTestArraySize; ++jdx)
- {
- double y = double(rawCounts[jdx]) - b;
- a = a + (y*y);
- }
- a = a/b;
- val = (unsigned long)(a*100);
- Printf("INFO: Chi-Squared value for Raw Data was %u.%02u\n",
- val/100, val % 100);
- }
- //
- // Output Run statistic statistic
- //
- {
- size_t total = 0;
- for (jdx = 0; jdx < kTestArraySize; ++jdx)
- total += runs[jdx];
- double y = 0.0;
- double b = double(total);
- for (jdx = 0; jdx < 9; ++jdx)
- {
- double c = ExpectedRuns(b, (short)jdx + 1);
- double d = double(runs[jdx]) - c;
- y = y + (d*d)/c;
- }
- unsigned long val = (unsigned long)(y*100);
- Printf("INFO: Chi-Squared value for Processed Data Runs was %u.%02u\n",
- val/100, val % 100);
- for (jdx = 9; jdx < kTestArraySize; ++jdx)
- if (runs[jdx] > 1)
- Printf("WARNING: Runs for #%u was %u\n", jdx + 1, runs[jdx]);
- total = 0;
- for (jdx = 0; jdx < kTestArraySize; ++jdx)
- total += rawRuns[jdx];
- y = 0.0;
- b = double(total);
- for (jdx = 0; jdx < 9; ++jdx)
- {
- double c = ExpectedRuns(b, (short)jdx + 1);
- double d = double(rawRuns[jdx]) - c;
- y = y + (d*d)/c;
- }
- val = (unsigned long)(y*100);
- Printf("INFO: Chi-Squared value for Raw Data Runs was %u.%02u\n",
- val/100, val % 100);
- for (jdx = 9; jdx < kTestArraySize; ++jdx)
- if (rawRuns[jdx] > 1)
- Printf("WARNING: Runs for #%u was %u\n", jdx + 1, rawRuns[jdx]);
- }
- Printf("INFO: smallest was %lu, largest was %lu, out of %lu\n",
- small, large, range);
- Printf("INFO: Closest numbers were separated by %lu\n",
- clos);
- }
- }
-
- /**********************************************************************
- ** PUBLIC EndTest
- ***********************************************************************/
-
- void TTestRandom::EndTest(BooleanParm verbose, BooleanParm)
- {
- if (verbose)
- Printf("INFO: End of Random test\n");
- }
-